package chat

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"strconv"

	netpack "im/im_server/proto"

	"github.com/go-redis/redis/v9"
)

type RedisCmd struct {
	redisClient *redis.Client
}

func (s *RedisCmd) HGetRedisPlayerValue(ctx context.Context, key string, filed string) (*netpack.DBPlayer, error) {
	db_player_data := &netpack.DBPlayer{}
	value, err := s.redisClient.HGet(ctx, key, filed).Result()
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal([]byte(value), db_player_data)
	if err != nil {
		return nil, err
	}
	return db_player_data, nil
}

func (s *RedisCmd) GetRedisAccountValue(ctx context.Context, key string) (int64, error) {
	value, err := s.redisClient.Get(ctx, key).Result()
	if err != nil {
		return -1, err
	}

	playerId, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return -1, nil
	}
	return playerId, nil
}

func (s *RedisCmd) GetRedisIncrByValue(ctx context.Context, key string) (int64, error) {
	value, err := s.redisClient.IncrBy(ctx,
		key, rand.Int63n(1000)).Result()
	if err != nil {
		return -1, err
	}
	return value, nil
}

func (s *RedisCmd) SetNXRedisAccountValue(ctx context.Context, key string, value string) error {
	cmd, err := s.redisClient.SetNX(ctx, key, value, 0).Result()
	if err != nil {
		return err
	}

	if !cmd {
		return fmt.Errorf("setnx redis_account exist:%v", key)
	}
	return nil
}

func (s *RedisCmd) HSetNXRedisPlayerValue(
	ctx context.Context, key string, filed string, value string) error {
	cmd, err := s.redisClient.HSetNX(ctx, key, filed, value).Result()
	if err != nil {
		return err
	}

	if !cmd {
		return fmt.Errorf("hsetnx redis_player exist:%v", key)
	}
	return nil
}

func (s *RedisCmd) SetNXRedisRoomNameValue(ctx context.Context, key string, value string) error {
	cmd, err := s.redisClient.SetNX(ctx, key, value, 0).Result()
	if err != nil {
		return err
	}

	if !cmd {
		return fmt.Errorf("hsetnx redis_room_name exist:%v", key)
	}
	return nil
}

func (s *RedisCmd) ExistRedisValue(tx context.Context, key string) error {
	err := s.redisClient.Exists(ctx, key).Err()
	if err != nil {
		return err
	}
	return nil
}

func (s *RedisCmd) HGetedisRoomValue(ctx context.Context, key string, filed string) (*netpack.DBChatRoom, error) {
	value, err := s.redisClient.HGet(ctx, key, filed).Result()
	if err != nil {
		return nil, err
	}

	dbChatRoomData := &netpack.DBChatRoom{}
	err = json.Unmarshal([]byte(value), dbChatRoomData)
	if err != nil {
		return nil, err
	}
	return dbChatRoomData, nil
}

func (s *RedisCmd) SMembersRedisRoomMemberListValue(ctx context.Context, key string) ([]*netpack.DBChatRoomMember, error) {
	memberList, err := s.redisClient.SMembers(ctx, key).Result()
	if err != nil {
		return nil, err
	}

	if len(memberList) == 0 {
		return nil, nil
	}

	dbChatRoomMemberList := make([]*netpack.DBChatRoomMember, 0, len(memberList))
	for _, member := range memberList {
		dbChatRoomMemberData := &netpack.DBChatRoomMember{}
		err = json.Unmarshal([]byte(member), dbChatRoomMemberData)
		if err != nil {
			return nil, err
		}
		dbChatRoomMemberList = append(dbChatRoomMemberList, dbChatRoomMemberData)
	}
	return dbChatRoomMemberList, nil
}

func (s *RedisCmd) GetRedisRoomNameValue(ctx context.Context, key string) (int64, error) {
	value, err := s.redisClient.Get(ctx, key).Result()
	if err != nil {
		return -1, err
	}

	roomId, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return -1, nil
	}
	return roomId, nil
}

func (s *RedisCmd) TxPipielineRedisJoinRoomValue(ctx context.Context,
	key1 string, member1 string, key2 string, member2 string) error {
	pipe := s.redisClient.TxPipeline()

	err := pipe.SAdd(ctx, key1, member1).Err()
	if err != nil {
		return nil
	}

	err = pipe.SAdd(ctx, key2, member2).Err()
	if err != nil {
		return nil
	}

	_, err = pipe.Exec(ctx)
	if err != nil {
		return err
	}
	return nil
}

func (s *RedisCmd) TxPipielineRedisRoomValue(ctx context.Context,
	key1 string, member1 string, key2 string, member2 string,
	key3 string, filed string, value string) error {
	pipe := s.redisClient.TxPipeline()

	err := pipe.SAdd(ctx, key1, member1).Err()
	if err != nil {
		return nil
	}

	err = pipe.SAdd(ctx, key2, member2).Err()
	if err != nil {
		return nil
	}

	err = pipe.HSetNX(ctx, key3, filed, value).Err()
	if err != nil {
		return nil
	}

	_, err = pipe.Exec(ctx)
	if err != nil {
		return err
	}
	return nil
}

func (s *RedisCmd) LPushRedisChatValue(ctx context.Context, key string, db_chat_data *netpack.DBChat) error {
	value, err := json.Marshal(db_chat_data)
	if err != nil {
		return err
	}

	err = s.redisClient.LPush(ctx, key, value).Err()
	if err != nil {
		return err
	}
	return nil
}
